﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using GSSoftSL.Utility;
using GSSoftSL.Web;
using GSSoftSL.Web.Models;
using GSSoftSL.Web.Services;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

namespace GSSoftSL.ViewModel
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class DiemDanhViewModel : ViewModelBase
    {
        private GSSoftContext _dc;
        public GSSoftContext DC
        {
            get { return _dc; }
        }

        private DiemDanhInfo _info = new DiemDanhInfo();
        public DiemDanhInfo Info
        {
            get { return _info; }
        }

        private bool _isBusy = false;
        public bool IsBusy
        {
            get
            {
                return _isBusy;
            }
            set
            {
                if (_isBusy == value)
                {
                    return;
                }
                _isBusy = value;
                RaisePropertyChanged("IsBusy");
            }
        }

        /// <summary>
        /// Initializes a new instance of the DiemDanhViewModel class.
        /// </summary>
        public DiemDanhViewModel()
        {
            Init();
        }

        private void Init()
        {
            _dc = new GSSoftContext();//(GSSoftContext) context;
            IsBusy = true;
            _dc.Load(_dc.GetMonsQuery().OrderBy(n => n.ThuTu), LoadBehavior.RefreshCurrent, LoadMon_Completed, null);
        }

        private void LoadMon_Completed(LoadOperation<Mon> load)
        {
            var lstMon = load.Entities.ToList();
            lstMon.Insert(0, new Mon(){MaMon = "-1", TenMon = "- Chọn môn -"});
            Mons = lstMon.ToArray();
            
            IsBusy = false;
        }

        private Mon[] _mons = null;
        public Mon[] Mons
        {
            get
            {
                return _mons;
            }
            set
            {
                if (_mons == value)
                {
                    return;
                }
                _mons = value;
                RaisePropertyChanged("Mons");
                Mon = Mons[0];
            }
        }
        
        private Mon _mon = null;
        public Mon Mon
        {
            get
            {
                return _mon;
            }
            set
            {
                if (_mon == value)
                {
                    return;
                }
                _mon = value;
                
                LoadCommand.RaiseCanExecuteChanged();
                RaisePropertyChanged("Mon");
                Lops = null;
                Lop = null;
                KhoaHocs = null;
                KhoaHoc = null;
                if (_mon != null && _mon.MaMon != "-1")
                {
                    IsBusy = true;
                    _dc.Load(_dc.GetLopsQuery().Where(n => n.MaMon == _mon.MaMon).OrderBy(n => n.TenLop), LoadBehavior.RefreshCurrent, LoadLop_Completed,
                             null);
                }
            }
        }

        private void LoadLop_Completed(LoadOperation<Lop> load)
        {
            var lstLops = load.Entities.ToList();
            lstLops.Insert(0, new Lop(){MaLop = "-1", TenLop = "- Chọn lớp -"});
            Lops = lstLops.ToArray();
            if (Lops.Length > 0)
                Lop = Lops[0];
            IsBusy = false;
        }

        private Lop[] _lops = null;
        public Lop[] Lops
        {
            get
            {
                return _lops;
            }
            set
            {
                if (_lops == value)
                {
                    return;
                }
                _lops = value;
                RaisePropertyChanged("Lops");
                if (_lops != null && _lops.Length > 0)
                    Lop = _lops[0];
            }
        }

        private Lop _lop = null;
        public Lop Lop
        {
            get
            {
                return _lop;
            }
            set
            {
                if (_lop == value)
                {
                    return;
                }
                _lop = value;
                RaisePropertyChanged("Lop");
                KhoaHocs = null;
                KhoaHoc = null;
                if (_lop != null && _lop.MaLop != "-1")
                {
                    IsBusy = true;
                    _dc.Load(_dc.GetKhoaHocsQuery().Where(n => n.LopId == _lop.LopId).OrderBy(n => n.STT), LoadBehavior.RefreshCurrent, LoadKhoaHoc_Completed,
                             null);
                }
                LoadCommand.RaiseCanExecuteChanged();
            }
        }

        private void LoadKhoaHoc_Completed(LoadOperation<KhoaHoc> load)
        {
            var lstKhoaHocs = load.Entities.ToList();
            lstKhoaHocs.Insert(0, new KhoaHoc(){MaKhoaHoc = "-1", TenKhoaHoc = "- Chọn khóa học -"});
            KhoaHocs = lstKhoaHocs.ToArray();
            IsBusy = false;
        }

        private KhoaHoc[] _khoaHocs = null;
        public KhoaHoc[] KhoaHocs
        {
            get
            {
                return _khoaHocs;
            }
            set
            {
                if (_khoaHocs == value)
                {
                    return;
                }
                _khoaHocs = value;
                RaisePropertyChanged("KhoaHocs");
                if (_khoaHocs != null && _khoaHocs.Length > 0)
                    KhoaHoc = _khoaHocs[0];
            }
        }

        private KhoaHoc _khoaHoc = null;
        public KhoaHoc KhoaHoc
        {
            get
            {
                return _khoaHoc;
            }
            set
            {
                if (_khoaHoc == value)
                {
                    return;
                }
                _khoaHoc = value;
                RaisePropertyChanged("KhoaHoc");
                LoadCommand.RaiseCanExecuteChanged();
            }
        }
        
        private DateTime _ngayDiemDanh = DateTime.Now.Date;
        public DateTime NgayDiemDanh
        {
            get
            {
                return _ngayDiemDanh;
            }
            set
            {
                if (_ngayDiemDanh == value)
                {
                    return;
                }
                _ngayDiemDanh = value;
                RaisePropertyChanged("NgayDiemDanh");
            }
        }
        
        private int _buoiHoc = 0;
        public int BuoiHoc
        {
            get
            {
                return _buoiHoc;
            }
            set
            {
                if (_buoiHoc == value)
                {
                    return;
                }
                _buoiHoc = value;
                LoadCommand.RaiseCanExecuteChanged();
                RaisePropertyChanged("BuoiHoc");
            }
        }
        
        private DiemDanh _diemDanh = null;
        public DiemDanh DiemDanh
        {
            get
            {
                return _diemDanh;
            }
            set
            {
                if (_diemDanh == value)
                {
                    return;
                }
                _diemDanh = value;
                RaisePropertyChanged("DiemDanh");
            }
        }
        
        private EnumMode _mode = EnumMode.Unspecified;
        public EnumMode Mode
        {
            get
            {
                return _mode;
            }
            set
            {
                if (_mode == value)
                {
                    return;
                }
                _mode = value;
                RaisePropertyChanged("Mode");
            }
        }

        private DiemDanhCTInfo[] _listHocVien = null;
        public DiemDanhCTInfo[] ListHocVien
        {
            get
            {
                return _listHocVien;
            }
            set
            {
                if (_listHocVien == value)
                {
                    return;
                }
                _listHocVien = value;
                if (_listHocVien != null && _listHocVien.Length > 0)
                {
                    ListKhongVang = new ObservableCollection<DiemDanhCTInfo>(_listHocVien.Where(n => !n.Vang).ToList());
                    ListVang = new ObservableCollection<DiemDanhCTInfo>(_listHocVien.Where(n => n.Vang).ToList());
                }
                else
                {
                    ListKhongVang = ListVang = null;
                }
                RaisePropertyChanged("ListHocVien");
            }
        }

        private ObservableCollection<DiemDanhCTInfo> _listKhongVang = null;
        public ObservableCollection<DiemDanhCTInfo> ListKhongVang
        {
            get
            {
                return _listKhongVang;
            }
            set
            {
                if (_listKhongVang == value)
                {
                    return;
                }
                _listKhongVang = value;
                RaisePropertyChanged("ListKhongVang");
            }
        }

        private ObservableCollection<DiemDanhCTInfo> _listVang = null;
        public ObservableCollection<DiemDanhCTInfo> ListVang
        {
            get
            {
                return _listVang;
            }
            set
            {
                if (_listVang == value)
                {
                    return;
                }
                _listVang = value;
                RaisePropertyChanged("ListVang");
            }
        }
        
        private DiemDanhCTInfo _selectHVKhongVang = null;
        public DiemDanhCTInfo SelectHVKhongVang
        {
            get
            {
                return _selectHVKhongVang;
            }
            set
            {
                if (_selectHVKhongVang == value)
                {
                    return;
                }
                _selectHVKhongVang = value;
                RaisePropertyChanged("SelectHVKhongVang");
            }
        }
        
        private DiemDanhCTInfo _selectHVVang = null;
        public DiemDanhCTInfo SelectHVVang
        {
            get
            {
                return _selectHVVang;
            }
            set
            {
                if (_selectHVVang == value)
                {
                    return;
                }
                _selectHVVang = value;
                RaisePropertyChanged("SelectHVVang");
            }
        }
        
        /*private bool _coGiaoVien = false;
        public bool CoGiaoVien
        {
            get
            {
                return _coGiaoVien;
            }
            set
            {
                if (_coGiaoVien == value)
                {
                    return;
                }
                _coGiaoVien = value;
                RaisePropertyChanged("CoGiaoVien");
            }
        }*/

        private RelayCommand _loadCommand;
        /// <summary>
        /// Gets the LoadCommand.
        /// </summary>
        public RelayCommand LoadCommand
        {
            get
            {
                return _loadCommand
                    ?? (_loadCommand = new RelayCommand(
                                          () =>
                                          {
                                              if (Mon == null || Lop == null || KhoaHoc == null || BuoiHoc == -1)
                                              {
                                                  Mode = EnumMode.Unspecified;
                                                  return;
                                              }
                                              IsBusy = true;

                                              _dc.Load(_dc.GetDiemDanhsQuery()
                                                           .Where(n => n.KhoaHocId == KhoaHoc.KhoaHocId &&
                                                                       n.NgayDiemDanh == NgayDiemDanh.Date),
                                                       LoadBehavior.RefreshCurrent, LoadDiemDanh_Completed, null);
                                          },
                                          () => Mon != null && Lop != null && KhoaHoc != null && BuoiHoc != -1 && NgayDiemDanh > new DateTime(2012, 1, 1)));
            }
        }

        private void LoadDiemDanh_Completed(LoadOperation<DiemDanh> load)
        {
            if (load.HasError)
            {
                Mode = EnumMode.Error;
            }
            else
            {
                if (load.Entities.Any())
                {
                    DiemDanh tmp = load.Entities.First();
                    //DiemDanh = load.Entities.First();
                    _dc.GetDiemDanhCTInfo(_khoaHoc.KhoaHocId, tmp.DiemDanhId,
                                          loadCT =>
                                              {
                                                  if (loadCT.HasError)
                                                      Mode = EnumMode.Error;
                                                  else
                                                  {
                                                      ListHocVien = loadCT.Value;
                                                      DiemDanh = loadCT.UserState as DiemDanh;
                                                      _info.LopId = Lop.LopId;
                                                      _info.KhoaHocId = KhoaHoc.KhoaHocId;
                                                      _info.NgayDiemDanh = NgayDiemDanh;
                                                      _info.BuoiHoc = (EnumBuoiHoc) BuoiHoc;
                                                      _info.TenLop = Lop.TenLop;
                                                      _info.TenKhoaHoc = KhoaHoc.TenKhoaHoc;
                                                      _info.CoGiaoVien = DiemDanh.CoGiaoVien;
                                                      IsBusy = false;
                                                      Mode = EnumMode.Modified;
                                                  }
                                              }, tmp);
                }
                else
                {
                    _dc.GetDiemDanhDSHV(KhoaHoc.KhoaHocId,
                                        loadCT =>
                                            {
                                                ListHocVien = loadCT.Value;
                                                _info.LopId = Lop.LopId;
                                                _info.KhoaHocId = KhoaHoc.KhoaHocId;
                                                _info.NgayDiemDanh = NgayDiemDanh;
                                                _info.BuoiHoc = (EnumBuoiHoc)BuoiHoc;
                                                _info.TenLop = Lop.TenLop;
                                                _info.TenKhoaHoc = KhoaHoc.TenKhoaHoc;
                                                _info.CoGiaoVien = true;
                                                IsBusy = false;
                                                Mode = EnumMode.AddNew;
                                            }, null);
                }
            }
        }

        private RelayCommand _resetCommand;
        public RelayCommand ResetCommand
        {
            get
            {
                return _resetCommand
                    ?? (_resetCommand = new RelayCommand(
                                          () =>
                                              {
                                                  _info.LopId = null;
                                                  _info.KhoaHocId = null;
                                                  _info.BuoiHoc = null;
                                                  _info.NgayDiemDanh = null;
                                                  _info.TenLop = _info.TenKhoaHoc = "";
                                                  _info.CoGiaoVien = false;
                                                  DiemDanh = null;
                                                  ListHocVien = null;
                                              }));
            }
        }

        private RelayCommand _absentCommand;
        public RelayCommand AbsentCommand
        {
            get
            {
                return _absentCommand
                    ?? (_absentCommand = new RelayCommand(
                                          () =>
                                          {
                                              if (SelectHVKhongVang == null)
                                                  return;

                                              var tmp = SelectHVKhongVang;
                                              tmp.Vang = true;
                                              ListKhongVang.Remove(SelectHVKhongVang);
                                              ListVang.Add(tmp);
                                          }));
            }
        }

        private RelayCommand _unAbsentCommand;
        public RelayCommand UnAbsentCommand
        {
            get
            {
                return _unAbsentCommand
                    ?? (_unAbsentCommand = new RelayCommand(
                                          () =>
                                          {
                                              if (SelectHVVang == null)
                                                  return;

                                              var tmp = SelectHVVang;
                                              tmp.Vang = false;
                                              ListVang.Remove(SelectHVVang);
                                              ListKhongVang.Add(tmp);
                                          }));
            }
        }

        private RelayCommand _saveCommand;
        public RelayCommand SaveCommand
        {
            get
            {
                return _saveCommand
                    ?? (_saveCommand = new RelayCommand(
                                          () =>
                                          {
                                              if (_mode != EnumMode.AddNew && _mode != EnumMode.Modified)
                                                  return;
                                              ConfirmWindow.CreateNew("Bạn có muốn lưu?", Save);
                                          },
                                          () => true));
            }
        }

        private void Save()
        {
            if (_mode == EnumMode.AddNew)
            {
                DiemDanh = new DiemDanh();
                DiemDanh.DiemDanhId = Guid.NewGuid();
                DiemDanh.BuoiHoc = (int)(_info.BuoiHoc.HasValue ? _info.BuoiHoc.Value : EnumBuoiHoc.Sang);
                //DiemDanh.LopId = _info.LopId.Value;
                DiemDanh.KhoaHocId = _info.KhoaHocId.Value;
                DiemDanh.NgayDiemDanh = _info.NgayDiemDanh.Value;
                DiemDanh.NguoiTao = DiemDanh.NguoiCapNhat = UtilityFunction.GetCurrentUserId();
                DiemDanh.NgayTao = DiemDanh.NgayCapNhat = DateTime.Now;
                DiemDanh.SoLuongHV = ListHocVien.Length;
                DiemDanh.SoLuongVang = ListVang.Count;
                DiemDanh.CoGiaoVien = _info.CoGiaoVien;
                DiemDanhCT ct;
                List<DiemDanhCT> lst = new List<DiemDanhCT>();
                foreach (var item in this.ListVang)
                {
                    ct = new DiemDanhCT();
                    ct.MaHV = item.MaHV;
                    ct.DiemDanhId = DiemDanh.DiemDanhId;
                    ct.CoPhep = item.CoPhep;
                    ct.LyDo = item.LyDo;
                    lst.Add(ct);
                }
                _dc.DiemDanhAddNew(DiemDanh, lst, Save_Completed, null);
            }
            else if (_mode == EnumMode.Modified)
            {
                DiemDanh.KhoaHocId = _info.KhoaHocId.Value;
                DiemDanh.NgayDiemDanh = _info.NgayDiemDanh.Value;
                DiemDanh.NguoiCapNhat = UtilityFunction.GetCurrentUserId();
                DiemDanh.NgayCapNhat = DateTime.Now;
                DiemDanh.SoLuongHV = ListHocVien.Length;
                DiemDanh.SoLuongVang = ListVang.Count;
                DiemDanh.CoGiaoVien = _info.CoGiaoVien;
                DiemDanhCT ct;
                List<DiemDanhCT> lst = new List<DiemDanhCT>();
                foreach (var item in this.ListVang)
                {
                    ct = new DiemDanhCT();
                    ct.MaHV = item.MaHV;
                    ct.DiemDanhId = DiemDanh.DiemDanhId;
                    ct.CoPhep = item.CoPhep;
                    ct.LyDo = item.LyDo;
                    lst.Add(ct);
                }
                _dc.DiemDanhUpdate(DiemDanh, lst, Save_Completed, null);
            }
            _dc.RejectChanges();
        }

        private void Save_Completed(InvokeOperation operation)
        {
            if (!operation.HasError)
                MessageWindow.CreateNew("Lưu thành công.");
            else
                MessageWindow.CreateNew("Lưu không thành công.");
        }

        /// <summary>
        /// Lưu thông tin về đợt điểm danh hiện tại.
        /// </summary>
        public class DiemDanhInfo : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }

            
            private Guid? _lopId;
            public Guid? LopId
            {
                get
                {
                    return _lopId;
                }
                set
                {
                    if (_lopId == value)
                    {
                        return;
                    }
                    _lopId = value;
                    NotifyPropertyChanged("LopId");
                }
            }
            
            private Guid? _khoaHocId;
            public Guid? KhoaHocId
            {
                get
                {
                    return _khoaHocId;
                }
                set
                {
                    if (_khoaHocId == value)
                    {
                        return;
                    }
                    _khoaHocId = value;
                    NotifyPropertyChanged("KhoaHocId");
                }
            }
            
            private DateTime? _ngayDiemDanh;
            public DateTime? NgayDiemDanh
            {
                get
                {
                    return _ngayDiemDanh;
                }
                set
                {
                    if (_ngayDiemDanh == value)
                    {
                        return;
                    }
                    _ngayDiemDanh = value;
                    NotifyPropertyChanged("NgayDiemDanh");
                }
            }
            
            private EnumBuoiHoc? _buoiHoc;
            public EnumBuoiHoc? BuoiHoc
            {
                get
                {
                    return _buoiHoc;
                }
                set
                {
                    if (_buoiHoc == value)
                    {
                        return;
                    }
                    _buoiHoc = value;
                    NotifyPropertyChanged("BuoiHoc");
                }
            }
            
            private string _tenLop;
            public string TenLop
            {
                get
                {
                    return _tenLop;
                }
                set
                {
                    if (_tenLop == value)
                    {
                        return;
                    }
                    _tenLop = value;
                    NotifyPropertyChanged("TenLop");
                }
            }
            
            private string _tenKhoaHoc;
            public string  TenKhoaHoc
            {
                get
                {
                    return _tenKhoaHoc;
                }
                set
                {
                    if (_tenKhoaHoc == value)
                    {
                        return;
                    }
                    _tenKhoaHoc = value;
                    NotifyPropertyChanged("TenKhoaHoc");
                }
            }
            
            private bool _coGiaoVien = false;
            public bool CoGiaoVien
            {
                get
                {
                    return _coGiaoVien;
                }
                set
                {
                    if (_coGiaoVien == value)
                    {
                        return;
                    }
                    _coGiaoVien = value;
                    NotifyPropertyChanged("CoGiaoVien");
                }
            }

        }
    }

}